#ifndef SESSIONBASE_H_
#define SESSIONBASE_H_

#include <e32base.h>
#include "scatu/ServerDefs.h"

namespace scatu {

class RSessionBase : public ::RSessionBase
    {

public:

    TInt Connect()
        {
        TInt retry = 2;
        FOREVER
            {
            TInt r = CreateSession(KServerName(), TVersion(1, 0, 0), 1);
            if (r != KErrNotFound && r != KErrServerTerminated)
                return r;
            if (--retry == 0)
                return r;
            r = StartServer();
            if (r != KErrNone && r != KErrAlreadyExists)
                return r;
            }
        }

public:
    // Allow public access to these
    inline TInt SendReceive(TInt aFunction, const TIpcArgs &aArgs) const
        { return ::RSessionBase::SendReceive(aFunction, aArgs); }
    
    inline void SendReceive(TInt aFunction, const TIpcArgs &aArgs, TRequestStatus & aStatus) const
        { ::RSessionBase::SendReceive(aFunction, aArgs, aStatus); }

private:
    static TInt StartServer()
        {
        const TUidType serverUid(KNullUid, KNullUid, KServerUid3());
        RProcess server;
        TInt r = server.Create(KServerName(), KNullDesC, serverUid);
        if (r != KErrNone)
            return r;
        
        TRequestStatus stat;
        server.Rendezvous(stat);
        if (stat != KRequestPending)
            server.Kill(0);     // abort startup
        else
            server.Resume();    // logon OK - start the server
        User::WaitForRequest(stat);     // wait for start or death
        
        // we can't use the 'exit reason' if the server panicked as this
        // is the panic 'reason' and may be '0' which cannot be distinguished
        // from KErrNone
        r = (server.ExitType() == EExitPanic) ? KErrGeneral : stat.Int();
        server.Close();
        return r;
        }

    };
    
} // namespace scatu

#endif /* SESSIONBASE_H_ */
